﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Pixysoft.Framework.Configurations;
using System.IO;
using Pixysoft.Framework.Logs.Core;

namespace Pixysoft.Framework.Logs.Controller
{
    /// <summary>
    /// 模块A 对dll进行注册日志文件位置
    /// 模块B 发生异常，从stack获取模块A的dll，结合注册信息，获取日志未知
    /// 模块A 根据异常时间+模块B的日志 搜索异常发生时候的动态
    /// 
    /// 在每个模块初始化的时候注册即可。
    /// </summary>
    class LogRegisterController
    {
        private const int default_stacklevel = 2;

        private static volatile LogRegisterController instance;

        private static object syncRoot = new Object();

        public static LogRegisterController Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        instance = new LogRegisterController();
                    }
                }

                return instance;

            }
        }

        /// <summary>
        /// 日志通过反射堆栈 注册dll与文件名路径映射
        /// </summary>
        /// <param name="path"></param>
        /// <param name="filename"></param>
        /// <returns></returns>
        public string Register(string path, string filename)
        {
            StackTrace trace = new StackTrace(true);

            StackFrame frame = trace.GetFrame(default_stacklevel);

            string dll = frame.GetMethod().Module.Name;

            if (IsRegistered(dll))
                return null;

            StringBuilder builder = new StringBuilder();

            builder.Append(string.Format(StringHelper.default_tag_log, dll, filename, path));

            SingletonLogger.Append(StringHelper.default_log_filepath, "", StringHelper.default_log_postfix, builder.ToString());

            return dll;
        }

        /// <summary>
        /// 判断是否已经注册过
        /// </summary>
        /// <param name="dll"></param>
        /// <returns></returns>
        private bool IsRegistered(string dll)
        {
            if (!File.Exists(StringHelper.default_log_filepath + StringHelper.default_log_postfix))
                return false;

            IXmlCommand command = XmlManager.CreateCommand(StringHelper.default_log_filepath + StringHelper.default_log_postfix);

            command.Element = StringHelper.default_element_log;

            command.Constraints.And(StringHelper.default_attribute_dll).Equal(dll);

            return command.ExecuteReader().Node.Count > 0;
        }

        /// <summary>
        /// 判断是否已经注册过 dll为带后缀的全文件名
        /// </summary>
        /// <param name="dll"></param>
        /// <returns></returns>
        public LogDirectoryStruct GetRegisterFilepath(string dll)
        {
            if (!File.Exists(StringHelper.default_log_filepath + StringHelper.default_log_postfix))
                return null;

            IXmlCommand command = XmlManager.CreateCommand(StringHelper.default_log_filepath + StringHelper.default_log_postfix);

            command.Element = StringHelper.default_element_log;

            command.Constraints.And(StringHelper.default_attribute_dll).Equal(dll);

            IXmlTree tree = command.ExecuteReader();

            if (tree.Node.Count == 0)
                return null;

            return new LogDirectoryStruct(tree.Node[0].Properties[StringHelper.default_attribute_path],
                tree.Node[0].Properties[StringHelper.default_attribute_file]);
        }
    }
}
